//备注：拷贝代码请加上作者信息
//作者：王海涛
//邮箱：1126471088@qq.com
//版本：V1.0.0
#include "dac_bsp.h"
#include "misc.h"

/* 正弦波数据 */
static const unsigned short Sine12bit[] = Sin_12Bit_Buffer;


static WHT_DMA_Config_t WHT_DMA_Config_DAC_CH1;
static WHT_DMA_Config_t WHT_DMA_Config_DAC_CH2;


/*DAC GPIO初始化*/
static void WHT_DAC_BSP_GPIO_Init(const WHT_DAC_Config_t* config)
{
    WHT_GPIO_BSP.WHT_Set_Clock(config->Channel_Port, ENABLE);
    WHT_GPIO_BSP.WHT_Set_Mode(config->Channel_Port, config->Channel_Pin, Mode_Ain);
}
/*DAC 定时器触发配置*/
static void WHT_BSP_Timer_Trigger_Config(const WHT_DAC_Timer_Trigger_t* config)
{
    WHT_Timer_Config_t WHT_Timer_Config;
    WHT_Timer_Out_Trigger_Config_t WHT_Timer_Out_Trigger_Config;

    WHT_Timer_Out_Trigger_Config.Out_Trigger = Timer_Update;

    WHT_Timer_Config.Name = config->Name;
    WHT_Timer_Config.Cycle_ns = config->Cycle_ns;
    WHT_Timer_Config.Mode = Timer_Output_Trigger;
    WHT_Timer_Config.Config_Count = 1;
    WHT_Timer_Config.Config = &WHT_Timer_Out_Trigger_Config;
    WHT_Timer_BSP.WHT_Config(&WHT_Timer_Config);//配置定时器更新输出触发
    WHT_Timer_BSP.WHT_Start(&WHT_Timer_Config); //启动定时器
}
/*DAC 外部引脚触发配置*/
static void WHT_BSP_EXTI_Trigger_Config(const WHT_DAC_EXTI_Trigger_t* config)
{
    WHT_EXTI_Config_t WHT_EXTI_Config;

    WHT_EXTI_Config.Type = Exti_GPIO;
    WHT_EXTI_Config.Line = Exti_Line_Pin9;
    WHT_EXTI_Config.Trigger = Trigger_Rising;
    WHT_EXTI_Config.Mode = Mode_Event;
    WHT_EXTI_Config.Portx = config->Portx;
    WHT_EXTI_Config.Pinx = config->Pinx;
    if (WHT_EXTI_BSP.WHT_Register(&WHT_EXTI_Config) == SUCCESS)
    {
        WHT_EXTI_BSP.WHT_Config(&WHT_EXTI_Config);
    }
    else
    {
        //注册失败
    }
}
/*DAC DMA配置*/
static void WHT_DAC_BSP_Reset_DMA(WHT_DAC_Channel_enum Channel, const WHT_DAC_DMA_t* config)
{
    WHT_DMA_Config_t* WHT_DMA_Config;
    DMA_InitTypeDef DMA_InitStruct =
    {
        .DMA_Channel            = 0,                          //DMA通道
        .DMA_PeripheralBaseAddr = 0,                          //外设基地址
        .DMA_Memory0BaseAddr    = 0,                          //存储器地址
        .DMA_DIR                = DMA_DIR_MemoryToPeripheral, //M->P
        .DMA_BufferSize         = 0,                          //传输个数
        .DMA_PeripheralInc      = DMA_PeripheralInc_Disable,  //外设地址不递增
        .DMA_MemoryInc          = DMA_MemoryInc_Enable,       //存储器地址递增
        .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte,//外设数据大小为字节
        .DMA_MemoryDataSize     = DMA_MemoryDataSize_Byte,    //存储器数据大小为字节，跟外设数据大小相同
        .DMA_Mode               = DMA_Mode_Circular,          //循环传输模式
        .DMA_Priority           = DMA_Priority_Low,           //优先级最低
        .DMA_FIFOMode           = DMA_FIFOMode_Disable,       //FIFO模式
        .DMA_FIFOThreshold      = DMA_FIFOThreshold_1QuarterFull,//FIFO阈值
        .DMA_MemoryBurst        = DMA_MemoryBurst_Single,     //内存突发传输
        .DMA_PeripheralBurst    = DMA_PeripheralBurst_Single, //外设突发传输
    };

    if (config->state == DISABLE)
        return;
    
    WHT_DMA_Config = Channel == DAC_CH1 ? &WHT_DMA_Config_DAC_CH1 : &WHT_DMA_Config_DAC_CH2;
    WHT_DMA_BSP.WHT_Close(WHT_DMA_Config);
    switch (config->Data_Type)
    {
    case DAC_CH1_12Bit:
        DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
        DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
        break;
    case DAC_CH1_8Bit:
        DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
        DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
        break;
    case DAC_CH2_12Bit:
    case DAC_CH1_2_8Bit:
        DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
        DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
        break;
    case DAC_CH2_8Bit:
        DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
        DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
        break;
    case DAC_CH1_2_12Bit:
        DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
        DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
        break;
    default:
        break;
    }
    DMA_InitStruct.DMA_Channel = WHT_DMA_Config->Channel;
    DMA_InitStruct.DMA_PeripheralBaseAddr = config->Data_Type;
    DMA_InitStruct.DMA_Memory0BaseAddr = (unsigned int)config->Buffer;
    DMA_InitStruct.DMA_BufferSize = config->Count;
    WHT_DMA_Config->DMA_InitStruct = &DMA_InitStruct;

    while (WHT_DMA_Config->Info->BSP_Mutex == SET);//等待没有外设使用此通道的DMA
    WHT_DMA_Config->Info->BSP_Mutex = SET;         //DMA通道上锁
    WHT_DMA_BSP.WHT_Config(WHT_DMA_Config);        //配置当前DMA
    DAC_DMACmd(Channel, ENABLE);
}
/*DAC启动转换输出*/
static void WHT_DAC_BSP_Start_Stop(WHT_DAC_Channel_enum Channel, FunctionalState state)
{
    DAC_Cmd(Channel, state);
}
/*DAC 配置*/
static void WHT_DAC_BSP_Config(const WHT_DAC_Config_t* config)
{
    DAC_InitTypeDef  DAC_InitStruct;

    WHT_DAC_BSP_GPIO_Init(config);
	/* 使能DAC时钟 */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
	
    DAC_DMACmd(config->Channel, DISABLE);
    WHT_DAC_BSP_Start_Stop(config->Channel, DISABLE);
    DAC_InitStruct.DAC_Trigger = config->Trigger_Mode;          //触发转换选择
    DAC_InitStruct.DAC_WaveGeneration = DAC_WaveGeneration_None;//不使用波形发生器
    DAC_InitStruct.DAC_OutputBuffer = DAC_OutputBuffer_Enable;	//DAC输出缓冲
    //三角波振幅（本实验没有用到，可配置成任意值，但本结构体成员不能为空）
    DAC_InitStruct.DAC_LFSRUnmask_TriangleAmplitude = DAC_TriangleAmplitude_4095;
    DAC_Init(config->Channel, &DAC_InitStruct);

    switch (config->Trigger_Mode)
    {
    case DAC_Timer2_Trigger:
    case DAC_Timer4_Trigger:
    case DAC_Timer5_Trigger:
    case DAC_Timer6_Trigger:
    case DAC_Timer7_Trigger:
    case DAC_Timer8_Trigger:   WHT_BSP_Timer_Trigger_Config((WHT_DAC_Timer_Trigger_t*)config->Trigger_Config);break;
    case DAC_Exit_Lin9_Trigger:WHT_BSP_EXTI_Trigger_Config((WHT_DAC_EXTI_Trigger_t*)config->Trigger_Config);break;
    case DAC_Software_Trigger: break;
    default:return;
    }
    /*DAC的DMA注册*/
    WHT_DMA_Config_DAC_CH1.Stream = Stream_DAC_CH1;  //流
    WHT_DMA_Config_DAC_CH1.Channel = Channel_DAC_CH1;//通道
    if (WHT_DMA_BSP.WHT_Register(&WHT_DMA_Config_DAC_CH1) == ERROR)
    {
        /* code */
    }
    WHT_DMA_Config_DAC_CH2.Stream = Stream_DAC_CH2;  //流
    WHT_DMA_Config_DAC_CH2.Channel = Channel_DAC_CH2;//通道
    if (WHT_DMA_BSP.WHT_Register(&WHT_DMA_Config_DAC_CH2) == ERROR)
    {
        /* code */
    }
    WHT_DAC_BSP_Reset_DMA(config->Channel, config->DMA_Config);
}

/*DAC 写数据*/
static void WHT_DAC_BSP_Write(WHT_DAC_Data_Type_enum data_type, unsigned int value)
{
    *(volatile unsigned int*)data_type = value;
}


/*全局常量*/
const WHT_DAC_BSP_t WHT_DAC_BSP =
{
    .WHT_Config     = WHT_DAC_BSP_Config,
    .WHT_Reset_DMA  = WHT_DAC_BSP_Reset_DMA,
    .WHT_Start_Stop = WHT_DAC_BSP_Start_Stop,
    .WHT_Write      = WHT_DAC_BSP_Write,
};
